{
 "cells": [
  {
   "cell_type": "code",
   "id": "initial_id",
   "metadata": {
    "collapsed": true,
    "ExecuteTime": {
     "end_time": "2025-06-06T09:49:02.770952Z",
     "start_time": "2025-06-06T09:49:02.584623Z"
    }
   },
   "source": [
    "from pydantic import BaseModel\n",
    "from typing import List, Union\n",
    "\n",
    "\n",
    "class AirConditionerConfig(BaseModel):\n",
    "    power: bool\n",
    "    temperature: int\n",
    "    fan_speed: int\n",
    "    mode: str\n",
    "\n",
    "\n",
    "class LEDLightConfig(BaseModel):\n",
    "    led: bool\n",
    "\n",
    "\n",
    "class DeviceCall(BaseModel):\n",
    "    device_name: str\n",
    "    device_id: str\n",
    "    config: Union[AirConditionerConfig, LEDLightConfig]\n",
    "    order: int\n",
    "\n",
    "\n",
    "class DeviceCallsDynamic(BaseModel):\n",
    "    device_calls: List[DeviceCall]\n"
   ],
   "outputs": [],
   "execution_count": 1
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-06T07:23:58.415892Z",
     "start_time": "2025-06-06T07:23:53.749399Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import time\n",
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "a=ChatOpenAI(\n",
    "    model='gpt-4o-mini',\n",
    "     disable_streaming=True  # 明确禁用流式  \n",
    ")\n",
    "llm=a.with_structured_output(DeviceCallsDynamic)\n",
    "input_str=\"\"\"\n",
    "You are an AI assistant designed to control smart home devices. Your task is to interpret user requests, analyze device configurations, and create a structured DeviceCalls object to control these devices. Please follow these instructions carefully:\n",
    "\n",
    "First, review the available device configurations:\n",
    "\n",
    "<device_configs>\n",
    "[[Document(metadata={}, page_content='{\\n  \"product_id\": {\\n    \"type\": \"string\",\\n    \"description\": \"产品ID\",\\n    \"value\": \"mD97Vya1hi\"\\n  },\\n  \"device_name\": {\\n    \"type\": \"string\",\\n    \"description\": \"设备名称\",\\n    \"value\": \"d1\"\\n  },\\n  \"device_type\": \"LED Light\",\\n  \"params\": {\\n    \"type\": \"object\",\\n    \"description\": \"控制参数，字典格式\",\\n    \"properties\": {\\n      \"led\": {\\n        \"type\": \"boolean\",\\n        \"description\": \"LED开关状态\",\\n        \"value_range\": \"true/false\"\\n      }\\n    }\\n  }\\n}'), Document(metadata={}, page_content='{\\n  \"product_id\": {\\n    \"type\": \"string\",\\n    \"description\": \"产品ID\",\\n    \"value\": \"aX23Jrf5xy\"\\n  },\\n  \"device_name\": {\\n    \"type\": \"string\",\\n    \"description\": \"设备名称\",\\n    \"value\": \"空调\"\\n  },\\n  \"device_type\": \"Air Conditioner\",\\n  \"params\": {\\n    \"type\": \"object\",\\n    \"description\": \"控制参数，字典格式\",\\n    \"properties\": {\\n      \"power\": {\\n        \"type\": \"boolean\",\\n        \"description\": \"开关状态\",\\n        \"value_range\": \"true/false\"\\n      },\\n      \"temperature\": {\\n        \"type\": \"integer\",\\n        \"description\": \"设定温度\",\\n        \"value_range\": \"16-30\"\\n      },\\n      \"fan_speed\": {\\n        \"type\": \"integer\",\\n        \"description\": \"风速级别\",\\n        \"value_range\": \"1-5\"\\n      },\\n      \"mode\": {\\n        \"type\": \"string\",\\n        \"description\": \"空调模式\",\\n        \"value_range\": \"冷/热/除湿/自动\"\\n      }\\n    }\\n  }\\n}')]]\n",
    "</device_configs>\n",
    "\n",
    "Now, consider the user's request:\n",
    "\n",
    "<question>\n",
    "content='帮我开灯，开空调' additional_kwargs={} response_metadata={} id='3753596e-5f89-4ac8-b7af-95b046df8ea9'\n",
    "</question>\n",
    "\n",
    "Additionally, take into account this supplementary information:\n",
    "\n",
    "<additional_info>\n",
    " \n",
    "</additional_info>\n",
    "\n",
    "To process the user's request and control the devices, follow these steps:\n",
    "\n",
    "1. Analyze the question to understand the user's intent.\n",
    "2. Identify which device(s) need to be controlled based on the question and device_configs.\n",
    "3. Review the additional_info for any relevant context or suggestions.\n",
    "4. Determine the appropriate parameters for each device based on the device_configs and the user's request.\n",
    "5. If any information is ambiguous or missing, make a reasonable assumption based on the additional_info or common sense.\n",
    "6. Prepare the DeviceCalls object, ensuring all required fields are filled correctly.\n",
    "\n",
    "Important considerations:\n",
    "- Use only the exact parameter names and value ranges specified in device_configs.\n",
    "- Include all parameters for each device in the params field, even if you're not changing them all.\n",
    "- Be user-friendly and consider comfort and efficiency in your decisions.\n",
    "- If you can't fulfill the request with the given information, explain why in your response.\n",
    "\n",
    "Before providing your final output, break down the request, analyze the device configurations, and plan your device calls inside <device_control_analysis> tags. This analysis should include:\n",
    "- A list of each relevant device and its parameters\n",
    "- Consideration of potential conflicts or dependencies between devices\n",
    "- A step-by-step plan for creating the DeviceCalls object\n",
    "\n",
    "This will help ensure a thorough interpretation of the data and proper structuring of the DeviceCalls object.\n",
    "\n",
    "Your final output should be a structured DeviceCalls object as defined below:\n",
    "\n",
    "```python\n",
    "class DeviceCall(BaseModel, Generic[ConfigT]):\n",
    "    device_name: str\n",
    "    device_id: str\n",
    "    config: ConfigT = Field(\n",
    "        description=\"the params for device_call which comes from the device_configs\",\n",
    "        json_schema_extra={\"additionalProperties\": False}  # 明确禁止额外属性\n",
    "    )\n",
    "    order: int = Field(\n",
    "        description=\"The order of the device call in the scene.\",\n",
    "    )\n",
    "\n",
    "\n",
    "class DeviceCalls(BaseModel, Generic[ConfigT]):\n",
    "    device_calls: List[DeviceCall[ConfigT]] = Field(\n",
    "        description=\"List of device calls.\",\n",
    "    )\n",
    "```\n",
    "\n",
    "Ensure that your output strictly adheres to this structure and includes all necessary information for each device call.\n",
    "\n",
    "Now, please process the input and provide your response according to these instructions.\n",
    "\"\"\"\n",
    "start_time = time.time()  \n",
    "response=llm.invoke(input_str,)\n",
    "end_time = time.time()  \n",
    "print(f\"Response received in {end_time - start_time:.2f} seconds\")  \n",
    "print(f\"Response type: {type(response)}\")  \n",
    "print(response)\n",
    "# print(\"Raw response:\", response[\"raw\"])  \n",
    "# print(\"Parsing error:\", response[\"parsing_error\"])\n"
   ],
   "id": "657863b6e0594e83",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Response received in 2.14 seconds\n",
      "Response type: <class '__main__.DeviceCallsDynamic'>\n",
      "device_calls=[DeviceCall(device_name='d1', device_id='mD97Vya1hi', config=LEDLightConfig(led=True), order=1), DeviceCall(device_name='空调', device_id='aX23Jrf5xy', config=AirConditionerConfig(power=True, temperature=24, fan_speed=3, mode='冷'), order=2)]\n"
     ]
    }
   ],
   "execution_count": 11
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-06T07:24:40.908979Z",
     "start_time": "2025-06-06T07:24:36.177472Z"
    }
   },
   "cell_type": "code",
   "source": [
    "a=ChatOpenAI(\n",
    "    model='gpt-4o-mini',\n",
    "     disable_streaming=True  # 明确禁用流式  \n",
    ")\n",
    "b=ChatOpenAI(\n",
    "    model='gpt-4o-mini',\n",
    "     \n",
    ")"
   ],
   "id": "421b8b8f73bb43a7",
   "outputs": [],
   "execution_count": 13
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-06T07:25:09.536983Z",
     "start_time": "2025-06-06T07:25:02.526140Z"
    }
   },
   "cell_type": "code",
   "source": "a.invoke(\"给我讲一段故事\")",
   "id": "2b86ae5b18074d00",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='在一个宁静的小村庄里，住着一位年迈的老奶奶，她有一座神奇的花园。这个花园里盛开着各种各样的花朵，每一朵花都有自己的故事。每当夜幕降临，村里的孩子们就会围坐在老奶奶的身边，期待她讲述花朵的秘密。\\n\\n有一天，老奶奶带着孩子们走进花园，指着一朵金色的向日葵说：“这是希望之花，用阳光和爱心浇灌，它能带给人们勇气和力量。”孩子们听后纷纷在心里种下了希望的种子。\\n\\n接着，老奶奶又指向一朵碧蓝的风铃草：“它代表友谊，友谊就像这花一样，美丽而脆弱，需要我们用真诚去呵护。”孩子们互相看了看，决定更加珍惜彼此的朋友。\\n\\n最后，老奶奶指着一朵洁白的玫瑰：“这是纯真的象征，只有真诚的心才能让它绽放。”孩子们默默地许下心愿，希望能一直保持真诚和善良。\\n\\n随着夜幕降临，星星在天空中闪烁，孩子们在花园中感受着美好与温暖，带着老奶奶的教诲回到了各自的家。日子一天天过去，孩子们在生活中践行着这些道理，而老奶奶的花园也在他们的心中留下了永恒的烙印。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 362, 'prompt_tokens': 13, 'total_tokens': 375, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_62a23a81ef', 'id': 'chatcmpl-BfLjkBtWqqXX5UcHKij69VspdqghO', 'finish_reason': 'stop', 'logprobs': None}, id='run-5bc36b25-23a4-49d9-ac67-0588af9d9a91-0', usage_metadata={'input_tokens': 13, 'output_tokens': 362, 'total_tokens': 375, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 16
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-06T07:24:58.339057Z",
     "start_time": "2025-06-06T07:24:50.178409Z"
    }
   },
   "cell_type": "code",
   "source": "b.invoke(\"给我讲一段故事\")",
   "id": "b9abcca221a03bf8",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='在一个宁静的小村庄里，住着一个年轻的女孩，名叫小月。小月从小就对星空充满了好奇，每当夜幕降临，她便会在村子外的小山坡上仰望星辰，幻想着那些星星背后的故事。\\n\\n有一天，小月在山坡上发现了一颗光芒四射的流星，她闭上眼睛，默默许下愿望：希望能够探索星空，了解每颗星星的名字和它们的故事。就在她睁开眼睛的那一瞬间，一位身穿星辰袍子的老者出现在她面前。\\n\\n“我听到了你的愿望，”老者微笑着说，“我是星空的守护者，你愿意和我一起去探索宇宙吗？”小月惊喜地答应了，随即被带上了一艘璀璨的宇宙飞船。\\n\\n他们穿越了无数星系，游历了不同的星球。小月看到火焰般的红色星球、冰雪覆盖的白色星球和充满奇幻生物的色彩斑斓的星球。老者一边飞行，一边给小月讲述每颗星星的故事：有的星星是勇士的化身，有的则是守护爱情的象征。\\n\\n经过无数的冒险，小月渐渐理解了宇宙的奥秘与人间的情感。最终，老者带着小月回到村庄的山坡上。他微笑着告诉她：“每颗星星都在某个地方闪耀，而你的梦想和勇气也会像星星一样，指引你前行。”\\n\\n自此以后，小月不仅仰望星空，更以星空为指引，勇敢追寻自己的梦想，成为了村庄里最优秀的天文学家。每当夜晚降临，她总会带着孩子们一起仰望星空，讲述那些星星的故事，让他们也能在无垠的宇宙中找到属于自己的光芒。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 469, 'prompt_tokens': 13, 'total_tokens': 482, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_34a54ae93c', 'id': 'chatcmpl-BfLjXgwGBepOdBnKPDg2PGrZNwHrM', 'finish_reason': 'stop', 'logprobs': None}, id='run-8ed48a2f-7f94-4584-941d-786b0c376feb-0', usage_metadata={'input_tokens': 13, 'output_tokens': 469, 'total_tokens': 482, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 15
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-06T09:52:15.807555Z",
     "start_time": "2025-06-06T09:52:14.642368Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from HomeBuddyAgent.agent import graph\n",
    "from IPython.display import Image, display\n",
    "\n",
    "try:\n",
    "    display(Image(graph.get_graph().draw_mermaid_png()))\n",
    "except Exception:\n",
    "    # This requires some extra dependencies and is optional\n",
    "    pass"
   ],
   "id": "f5263dcc423c6ec9",
   "outputs": [],
   "execution_count": 4
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
